package com.github.data_manage.controller

import cn.idev.excel.EasyExcel
import cn.idev.excel.support.ExcelTypeEnum
import com.github.data_manage.common.CommonPage
import com.github.data_manage.common.CommonResult
import com.github.data_manage.common.ResultCode
import com.github.data_manage.dao.FundInvestmentsDao
import com.github.data_manage.dao.InvestmentsDao
import com.github.data_manage.dao.PersonInvestmentExperienceDao
import com.github.data_manage.domain.po.Company
import com.github.data_manage.domain.po.Investments
import com.github.data_manage.domain.vo.InvestmentsPageParam
import com.github.data_manage.enum.SortType
import com.github.data_manage.util.PageUtil
import io.swagger.v3.oas.annotations.Operation
import jakarta.persistence.criteria.Predicate
import jakarta.servlet.http.HttpServletResponse
import jakarta.transaction.Transactional
import org.springframework.data.domain.Sort
import org.springframework.data.jpa.domain.Specification
import org.springframework.http.HttpHeaders
import org.springframework.http.MediaType
import org.springframework.util.StringUtils
import org.springframework.validation.annotation.Validated
import org.springframework.web.bind.annotation.*
import org.springframework.web.multipart.MultipartFile
import java.math.BigDecimal
import java.net.URLEncoder
import java.nio.charset.StandardCharsets

/**
 * @author chenhainan
 * @since 2024-08-15 09:12
 */
@RestController
@RequestMapping(value = ["/investments"])
class InvestmentsController(
    private val investmentsDao: InvestmentsDao,
    private val fundInvestmentsDao: FundInvestmentsDao,
    private val personInvestmentsDao: PersonInvestmentExperienceDao
) {

    @Operation(description = "新增/编辑投资案例")
    @PostMapping("/saveOrUpdate")
    @Transactional(rollbackOn = [Exception::class])
    fun saveOrUpdatePerson(@Validated @RequestBody investments: Investments): CommonResult<String> {
        if (investments.aum == null) {
            investments.aum = BigDecimal.ZERO
        }
        investmentsDao.save(investments)
        fundInvestmentsDao.updateInvestmentNameByInvestmentId(investments.id!!, investments.name!!)
        personInvestmentsDao.updateInvestmentNameByInvestmentId(investments.id!!, investments.name!!)
        return CommonResult.success(ResultCode.SUCCESS.message)
    }

    @Operation(description = "投资案例列表")
    @PostMapping(value = ["/list"])
    fun getInvestmentsList(@RequestBody investmentsPageParam: InvestmentsPageParam): CommonResult<CommonPage<Investments>> {
        val condition = Specification<Investments> { root, _, builder ->
            val conditions = mutableListOf<Predicate>()
            if (StringUtils.hasText(investmentsPageParam.investmentName)) {
                conditions.add(
                    builder.like(
                        root.get<String>("name"),
                        "%${investmentsPageParam.investmentName}%"
                    )
                )
            }
            return@Specification builder.and(*conditions.toTypedArray())
        }
        val page = PageUtil.buildJpaPage<Investments>(investmentsPageParam.pageNum, investmentsPageParam.pageSize)
            .let {
                if (investmentsPageParam.sort != null) {
                    when (investmentsPageParam.sort!!.sortType) {
                        SortType.DESC -> it.withSort(Sort.by(investmentsPageParam.sort!!.field).descending())
                        SortType.ASC -> it.withSort(Sort.by(investmentsPageParam.sort!!.field).ascending())
                    }

                } else {
                    it.withSort(Sort.by("id").descending())
                }
            }

        return CommonResult.success(CommonPage.restPage(investmentsDao.findAll(condition, page)))
    }

    @Operation(description = "投资案例信息详情")
    @GetMapping(value = ["/details"])
    fun getInvestmentsDetailsById(@RequestParam investmentsId: Int): CommonResult<Investments> {
        return investmentsDao.findById(investmentsId)
            .map { investments ->
                CommonResult.success(investments)
            }.orElse(CommonResult.failed(ResultCode.NO_DATA.message))
    }

    @GetMapping("/importTemplate")
    @Operation(description = "导入模板下载")
    fun getImportTemplate(response: HttpServletResponse) {
        response.contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE
        response.characterEncoding = StandardCharsets.UTF_8.name()
        response.setHeader(
            HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + URLEncoder.encode(
                "投资案例信息导入.xlsx", StandardCharsets.UTF_8
            )
        )
        response.outputStream.use { fos ->
            EasyExcel.write(fos, Investments::class.java)
                .excelType(ExcelTypeEnum.XLSX)
                .sheet("投资案例模板")
                .doWrite {
                    emptyList<Investments>()
                }
        }
    }


    @PostMapping("/importTemplate")
    @Operation(description = "模板导入")
    @Transactional(rollbackOn = [Exception::class])
    fun importTemplate(@RequestParam("excelFile") excelFile: MultipartFile): CommonResult<String> {
        excelFile.inputStream.use { fis ->
            EasyExcel.read(fis)
                .head(Investments::class.java)
                .doReadAllSync<Investments>()
                .forEach { investments ->
                    if (!StringUtils.hasText(investments.name)) {
                        return@forEach
                    }
                    investments.aum = investments.aum ?: BigDecimal.ZERO
                    if (investmentsDao.findByName(investments.name!!) == null) {
                        investments.aum = investments.aum ?: BigDecimal.ZERO
                        investmentsDao.save(investments)
                    }
                }
        }
        return CommonResult.success(ResultCode.SUCCESS.message);
    }
}
